const std = @import("std");
const database = @import("../database/db.zig");
const article_model = @import("../model/article.zig");

/// 获取首页文章列表
pub fn getHomeArticles() ![]article_model.Article {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\SELECT id, title, description, content, istop, cate_name, created_at, updated_at FROM article ORDER BY created_at DESC LIMIT 8 OFFSET 0
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const rows = try stmt.all(
        article_model.Article,
        allocator,
        .{},
        .{},
    );

    return rows;
}

/// 获取文章详情
pub fn getArticleDetail(id: u32) !?article_model.Article {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\SELECT id, title, description, content, istop, cate_name, created_at, updated_at FROM article WHERE id = ?
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const row = try stmt.oneAlloc(article_model.Article, allocator, .{}, .{
        .id = id,
    });

    if (row) |r| {
        return r;
    } else {
        return null;
    }
}

/// 获取分类下的文章列表
pub fn getArticlesByCateName(cate_name: []const u8) ![]article_model.Article {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\SELECT id, title, description, content, istop, cate_name, created_at, updated_at FROM article WHERE cate_name = ? ORDER BY created_at DESC
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const rows = try stmt.all(
        article_model.Article,
        allocator,
        .{},
        .{ .cate_name = cate_name },
    );

    return rows;
}

/// 文章搜索
pub fn searchArticles(keyword: []const u8) ![]article_model.Article {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\SELECT id, title, description, content, istop, cate_name, created_at, updated_at FROM article WHERE title LIKE $title ORDER BY created_at DESC
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const word = try std.fmt.allocPrint(allocator, "{s}%", .{keyword});

    const rows = try stmt.all(
        article_model.Article,
        allocator,
        .{},
        .{ .title = word },
    );

    return rows;
}

/// 归档文章列表
pub fn getArchiveArticles() ![]article_model.ArchiveArticle {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\SELECT id, title, cate_name, created_at FROM article
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const rows = try stmt.all(
        article_model.ArchiveArticle,
        allocator,
        .{},
        .{},
    );

    return rows;
}

/// 查询文章总数
pub fn getArticleTotalCount() !u32 {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\SELECT COUNT(id) as count FROM article
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    const row = try stmt.one(u32, .{}, .{});

    if (row) |count| {
        return count;
    } else {
        return 0;
    }
}

/// 获取文章列表
pub fn getArticleListPaginate(page_size: u32, page_num: u32) ![]article_model.Article {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\SELECT id, title, description, content, istop, cate_name, created_at, updated_at FROM article ORDER BY id ASC LIMIT $limit OFFSET $offset
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const limit = page_size; // 每页显示数量
    const offset = page_size * (page_num - 1); // 跳过数量

    const rows = try stmt.all(
        article_model.Article,
        allocator,
        .{},
        .{ .limit = limit, .offset = offset },
    );

    return rows;
}

/// 添加文章
pub fn addArticle(article: article_model.ArticleDtoForCreate) !bool {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\INSERT INTO article (title, description, content, istop, cate_name, created_at, updated_at) VALUES ($title, $description, $content, $istop, $cate_name, $created_at, $updated_at)
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    stmt.exec(.{}, .{
        .title = article.title,
        .description = article.description,
        .content = article.content,
        .istop = article.istop,
        .cate_name = article.cate_name,
        .created_at = article.created_at,
        .updated_at = article.updated_at,
    }) catch {
        return false;
    };

    return true;
}

/// 更新文章
pub fn updateArticle(article: article_model.ArticleDtoForEdit) !bool {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\UPDATE article SET title = $title, description = $description, content = $content, istop = $istop, cate_name = $cate_name, updated_at = $updated_at WHERE id = $id
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    stmt.exec(.{}, .{
        .title = article.title,
        .description = article.description,
        .content = article.content,
        .istop = article.istop,
        .cate_name = article.cate_name,
        .updated_at = article.updated_at,
        .id = article.id,
    }) catch {
        return false;
    };

    return true;
}

/// 删除文章
pub fn deleteArticleById(id: u32) !bool {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\DELETE FROM article WHERE id = $id
    ;

    var stmt = try db.prepare(query);
    defer stmt.deinit();

    stmt.exec(.{}, .{ .id = id }) catch {
        return false;
    };

    return true;
}

/// 批量删除文章
pub fn deleteArticleBatch(ids: []u32) !bool {
    var db = try database.OpenDb();
    defer db.deinit();

    const query =
        \\DELETE FROM article WHERE id = $id
    ;

    for (ids) |id| {
        var stmt = try db.prepare(query);
        defer stmt.deinit();

        stmt.exec(.{}, .{ .id = id }) catch {
            return false;
        };
    }

    return true;
}
